package me.wangshier.jms.taco.localcache;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: tongqianwen
 * @Date: 2024/12/20
 */
public class DefaultLocalCache<V> implements LocalCache<V> {
    private static final int DEFAULT_CAPACITY = 1024;

    private static final int MAX_CAPACITY = 2048;

    private static final int DAFAULT_THREAD_SIZE = 1;

    private int maxSize;

    private volatile ConcurrentHashMap<String, V> map;

    private ConcurrentHashMap<String, Long> timeOutMap;

    private ScheduledExecutorService executorService;

    public DefaultLocalCache() {
        maxSize = MAX_CAPACITY;
        map = new ConcurrentHashMap<>(DEFAULT_CAPACITY);
        timeOutMap = new ConcurrentHashMap<>(DEFAULT_CAPACITY);
        executorService = new ScheduledThreadPoolExecutor(DAFAULT_THREAD_SIZE);
    }

    public DefaultLocalCache(int maxSize) {
        this.maxSize = maxSize;
        map = new ConcurrentHashMap<>(DEFAULT_CAPACITY);
        timeOutMap = new ConcurrentHashMap<>(DEFAULT_CAPACITY);
        executorService = new ScheduledThreadPoolExecutor(DAFAULT_THREAD_SIZE);
    }

    @Override
    public boolean put(String key, V value) {
        if (checkCapacity()) {
            map.put(key, value);
        }
        return false;
    }

    @Override
    public boolean put(String key, V value, int seconds) {
        if (checkCapacity()) {

            map.put(key, value);
            if (seconds > 0) {
                timeOutMap.put(key, getTime(seconds));
                ClearTask task = new ClearTask(key);
                executorService.schedule(task, seconds, TimeUnit.SECONDS);
            }
        }
        return false;
    }

    private Long getTime(int seconds) {
        return System.currentTimeMillis() + seconds * 1000;
    }

    private boolean checkCapacity() {
        return map.size() < maxSize;
    }

    @Override
    public boolean isContainKey(String key) {
        return false;
    }

    @Override
    public V get(String key) {
        return map.get(key);
    }

    @Override
    public void remove(String key) {
        map.remove(key);
    }

    @Override
    public void shutdownNow() {
        if (executorService != null) {
            executorService.shutdownNow();
        }
    }


    // 缓存清除任务
    public class ClearTask implements Runnable {
        private String key;

        public ClearTask(String key) {
            this.key = key;
        }

        @Override
        public void run() {
            if (timeOutMap.contains(key)) {
                long expire = timeOutMap.get(key);
                if (expire > 0) {
                    long now = System.currentTimeMillis();
                    if (now > expire) {
                        remove(key);
                    }
                }
            }
        }
    }

}
